package com.erp.base.base;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Properties;

import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.erp.base.base.dialect.MySqlDialect;

@Intercepts({ @Signature(method = "query", type = Executor.class, args = { MappedStatement.class, Object.class,
		RowBounds.class, ResultHandler.class }) })
public class PageInterceptor implements Interceptor {
	private Dialect dialect;
	private static Field additionalParametersField;
	private final static Logger logger=LoggerFactory.getLogger(PageInterceptor.class);
	@Override
	public Object intercept(Invocation ivc) throws Throwable {
		// TODO Auto-generated method stub
		Object[] args = ivc.getArgs();
		MappedStatement ms = (MappedStatement) args[0];
		Object parameter = args[1];
		BoundSql boundSql = ms.getBoundSql(parameter);
		Executor executor = (Executor) ivc.getTarget();
		ResultHandler resultHandler = (ResultHandler) args[3];  
		Page pg = PageHelper.convertParameter(parameter);
		if(logger.isDebugEnabled()){
			logger.debug(" sql参数:"+parameter);
		}
		if (pg.getLimit() == -1) {
			if(logger.isDebugEnabled()){
				logger.debug(" sql语句:"+boundSql.getSql());
			}
			return ivc.proceed();
		}
		Map<String, Object> additionalParameters = (Map) additionalParametersField.get(boundSql);
		Long count = PageHelper.sqlCount(ms, executor, resultHandler, boundSql, parameter, additionalParameters);
		pg.setTotal(count);
		String pgSql = dialect.getLimitString(boundSql.getSql(), pg.getOffset(), pg.getLimit());
		if(logger.isDebugEnabled()){
			logger.debug(" 分页sql语句:"+pgSql);
		}
		CacheKey pageKey = executor.createCacheKey(ms, parameter, RowBounds.DEFAULT, boundSql);
		pageKey.update(pg.getOffset());
		pageKey.update(pg.getLimit());
		BoundSql pageBoundSql = new BoundSql(ms.getConfiguration(), pgSql, boundSql.getParameterMappings(), parameter);
		for (String key : additionalParameters.keySet()) {
			pageBoundSql.setAdditionalParameter(key, additionalParameters.get(key));
		}
		return executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, pageKey, pageBoundSql);
	}

	@Override
	public Object plugin(Object target) {
		// TODO Auto-generated method stub
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties props) {
		dialect =new MySqlDialect();
		try {
			additionalParametersField = BoundSql.class.getDeclaredField("additionalParameters");
			additionalParametersField.setAccessible(true);
		} catch (NoSuchFieldException e) {
			throw new RuntimeException(e);
		}
	}

}
